import axios, {
  AxiosError,
  AxiosRequestConfig,
  AxiosResponse,
  InternalAxiosRequestConfig,
} from "axios";
import getStatusMessage from "./status";
import { ElMessage } from "element-plus";

type BaseResponse<T = any> = {
  code: number;
  message: string;
  data: T;
  status: number;
};

const http = axios.create({
  timeout: 15000,
  baseURL: import.meta.env.VITE_APP_USE_MOCK
    ? import.meta.env.VITE_APP_MOCK_BASEURL
    : import.meta.env.VITE_APP_BASEURL,
});

http.interceptors.request.use(
  function (config: InternalAxiosRequestConfig) {
    return config;
  },
  function (error: AxiosError) {
    return Promise.reject(error);
  },
);

// 添加响应拦截器
http.interceptors.response.use(
  function (response: AxiosResponse) {
    // 2xx 范围内的状态码都会触发该函数。
    return response;
  },
  function (error: AxiosError) {
    // 超出 2xx 范围的状态码都会触发该函数。
    const { response } = error;
    if (response) {
      const msg = getStatusMessage(response.status);
      ElMessage.error(msg);
      return Promise.reject(error);
    }
    ElMessage.error("网络异常，请稍后再试");
    return Promise.reject(error);
  },
);

export function requestInstance<T = any>(
  config: AxiosRequestConfig,
): Promise<BaseResponse<T>> {
  return new Promise((resolve, reject) => {
    http
      .request<any, AxiosResponse<BaseResponse>>(config)
      .then((res: AxiosResponse<BaseResponse>) => {
        const data = res.data;
        if (data.code !== 0) {
          reject(data.message);
          ElMessage.error(data.message);
        } else {
          resolve(data as BaseResponse<T>);
        }
      });
  });
}

export function get<T = any, U = any>(
  config: AxiosRequestConfig,
  url: string,
  params?: U,
): Promise<BaseResponse<T>> {
  return requestInstance<T>({ ...config, url, params, method: "get" });
}
export function post<T = any, U = any>(
  config: AxiosRequestConfig,
  url: string,
  data?: U,
): Promise<BaseResponse<T>> {
  return requestInstance<T>({ ...config, url, data, method: "post" });
}
export function del<T = any, U = any>(
  config: AxiosRequestConfig,
  url: string,
  params?: U,
): Promise<BaseResponse<T>> {
  return requestInstance<T>({ ...config, url, params, method: "delete" });
}
export function put<T = any, U = any>(
  config: AxiosRequestConfig,
  url: string,
  data?: U,
): Promise<BaseResponse<T>> {
  return requestInstance<T>({ ...config, url, data, method: "put" });
}

export default http;
